package com.example.springboot.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.example.springboot.entity.Extent;
import com.example.springboot.entity.TileNodes;
import com.example.springboot.utils.RedisUtils;
import com.example.springboot.utils.SpringContextUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.utils.URIUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

@Log4j2
public class TileProxyServlet extends org.mitre.dsmiley.httpproxy.ProxyServlet {

    private RedisUtils redisUtils;

    @Override
    protected void service(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws ServletException, IOException {

        redisUtils = (RedisUtils) SpringContextUtils.getBean("redisUtils");

        String targetUri;

        String[] pathVariales = StringUtils.split(servletRequest.getRequestURI(), "/");

        if (pathVariales.length < 3) {
            return;
        }

        long level = Long.parseLong(pathVariales[0]);
        long x = Long.parseLong(pathVariales[1]);
        long y = Long.parseLong(pathVariales[2].replaceAll(".png", ""));

        String layerMeta = redisUtils.get("layers");

        TileNodes availableNode = getAvailabilityTileServer(transMetaJsonToNodes(layerMeta), x, y, level);

        targetUri = availableNode.getBaseUrl();

        servletRequest.setAttribute(ATTR_TARGET_URI, null);
        super.targetUri = targetUri;

        URI uri = null;
        try {
            uri = new URI(targetUri);
        } catch (URISyntaxException e) {
            log.error("创建URI对象出错, targetUri[{}]", targetUri, e);
        }
        servletRequest.setAttribute(ATTR_TARGET_HOST, null);
        super.targetHost = URIUtils.extractHost(uri);

        super.service(servletRequest, servletResponse);
    }

    public TileNodes getAvailabilityTileServer(TileNodes[] nodes, long x, long y, long level) {
        for (TileNodes node : nodes) {
            Extent[][] extents = node.getAvailable();
            if (extents.length < 1) {
                continue;
            }
            for (Extent[] extents1 : extents) {
                for (Extent extent : extents1) {
                    if (x <= extent.getEndX() && x >= extent.getStartX() && y <= extent.getEndY() && y >= extent.getStartY()) {
                        return node;
                    }
                }
            }
        }
        return new TileNodes();
    }

    public TileNodes[] transMetaJsonToNodes(String layerMeta) {
        JSONArray jsonArray = (JSONArray) JSON.parse(layerMeta);
        TileNodes[] nodes = new TileNodes[jsonArray.size()];
        for (int i = 0; i < jsonArray.size(); i++) {
            nodes[i] = JSON.toJavaObject((JSONObject) jsonArray.get(i), TileNodes.class);
        }
        return nodes;
    }
}
